﻿using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace CWM.Skinn
{
    public static partial class SkinnContext
    {
        public static class ContextUtility
        {
            internal class ContextBoneData
            {
                internal string name;
                internal Transform bone;
                internal bool hasChildInArray;

                public ContextBoneData() { }
                public ContextBoneData(Transform bone, Transform[] bones)
                {
                    name = bone ? bone.name : "null";
                    this.bone = bone;
                    hasChildInArray = HasChildInBoneArray(bone, bones);
                }

                private static bool HasChildInBoneArray(Transform bone, Transform[] bones)
                {
                    if (SkinnEx.IsNullOrEmpty(bones) || !bone) return false;
                    if (bone.childCount < 1) return false;
                    var childern = bone.GetAllChildren();
                    foreach (var item in childern) if (bones.GetIndex(item.GetInstanceID()) > -1) return true;
                    return false;
                }

                public static implicit operator bool(ContextBoneData x) { return x != null; }
            }

            internal static void ApplyMaterial(Material material)
            {
                foreach (var item in GetContextItems())
                {
                    var context = item.GetComponent<Renderer>();
                    if (SkinnEx.IsNullOrNotInAScene(context)) continue;
                    Undo.RegisterCompleteObjectUndo(context, "ApplyMaterial");
                    var materials = context.GetSharedMaterialsFromSubMeshes();
                    for (int i = 0; i < materials.Length; i++) materials[i] = material;
                    context.sharedMaterials = materials;
                }

                Finished();
            }

            internal static Dictionary<int, ContextBoneData> GetAllBones()
            {
                var allBones = new Dictionary<int, ContextBoneData>();
                foreach (var item in InstanceIDs)
                {
                    var go = SkinnEx.FindGameObject(item); if (!go) continue;

                    var skin = go.GetComponent<SkinnedMeshRenderer>();
                    if (!skin || !skin.sharedMesh ||  SkinnEx.IsNullOrEmpty(skin.sharedMesh.bindposes)
                    || SkinnEx.IsNullOrEmpty(skin.bones, skin.sharedMesh.bindposes.Length)) continue;

                    for (int i = 0; i < skin.bones.Length; i++)
                    {
                        var bone = skin.bones[i]; if (!bone) continue;
                        var boneID = skin.bones[i].gameObject.GetInstanceID();
                        if (!allBones.ContainsKey(boneID))
                            allBones.Add(boneID, new ContextBoneData(bone, skin.bones));
                    }
                }
                return allBones;
            }

            internal static List<string> GetAllBlendshapes()
            {
                var allShapes = new List<string>();
                foreach (var item in InstanceIDs)
                {
                    var go = SkinnEx.FindGameObject(item); if (!go) continue;
                    var skin = go.GetComponent<SkinnedMeshRenderer>();
                    if (!skin || !skin.sharedMesh)continue;
                    allShapes.AddRange(skin.sharedMesh.GetBlendshapeNames());
                }
                return allShapes;
            }

            internal static bool HasRequirements(ContextRequirements contextRequirements)
            {
                switch (contextRequirements)
                {
                    case ContextRequirements.Children:
                        {
                            if (Selection.gameObjects.Length > 1) return false;
                            var transform = (Selection.objects[0] as GameObject).GetComponent<Transform>();
                            if (!transform || transform.childCount < 1) return false;
                        }
                        break;
                    case ContextRequirements.SubMeshes:
                        {
                            if (Selection.gameObjects.Length > 1) return false;
                            var renderer = (Selection.objects[0] as GameObject).GetComponent<Renderer>();
                            if (!renderer || !SkinnEx.HasSharedMesh(renderer)) return false;
                            if (renderer.GetSharedMesh().subMeshCount < 2) return false;
                        }
                        break;
                    case ContextRequirements.SingleSubMesh:
                        {
                            if (Selection.gameObjects.Length > 1) return false;
                            var renderer = (Selection.objects[0] as GameObject).GetComponent<Renderer>();
                            if (!renderer || !SkinnEx.HasSharedMesh(renderer)) return false;
                            if (renderer.GetSharedMesh().subMeshCount > 1) return false;
                        }
                        break;
                    case ContextRequirements.RootBone:
                        {
                            if (Selection.gameObjects.Length > 1) return false;

                            var renderer = (Selection.objects[0] as GameObject).GetComponent<SkinnedMeshRenderer>();
                            if (!renderer || !SkinnEx.HasMinimumRequirements(renderer as Renderer)) return false;
                            if (!renderer.rootBone) return false;
                        }
                        break;
                    case ContextRequirements.SingleItem:
                        {
                            if (Selection.objects.Length > 1) return false;
                        }
                        break;
                    case ContextRequirements.MultipleItems:
                        {
                            int contextItemCount = Selection.gameObjects.Length;
                            if (contextItemCount < 2) return false;
                        }
                        break;
                    case ContextRequirements.CanPasteVertex:
                        {
                            if (Selection.gameObjects.Length > 1) return false;
                            var renderer = (Selection.objects[0] as GameObject).GetComponent<Renderer>();
                            if (!renderer || !SkinnEx.HasSharedMesh(renderer)) return false;
                            var copyRefMesh = CopyRef.SharedMesh();
                            if (!SkinnEx.CanApplyVertices(copyRefMesh, renderer.GetSharedMesh())) return false;
                        }
                        break;
                    case ContextRequirements.CanPasteBlendshape:
                        {
                            if (Selection.gameObjects.Length > 1) return false;
                            var renderer = (Selection.objects[0] as GameObject).GetComponent<Renderer>();
                            if (!renderer || !SkinnEx.HasSharedMesh(renderer)) return false;
                            var copyRefMesh = CopyRef.SharedMesh();
                            if (!SkinnEx.CanApplyVertices(copyRefMesh, renderer.GetSharedMesh())) return false;
                            if (copyRefMesh.blendShapeCount < 1 ) return false;
                        }
                        break;

                    case ContextRequirements.CanPasteLOD:
                        {
                            if (Selection.gameObjects.Length > 1) return false;
                            var renderer = (Selection.objects[0] as GameObject).GetComponent<Renderer>();
                            if (!renderer || !SkinnEx.HasSharedMesh(renderer)) return false;
                            var copyRefMesh = CopyRef.SharedMesh();
                            if (!copyRefMesh || renderer.GetSharedMesh().subMeshCount != copyRefMesh.subMeshCount) return false;
                        }
                        break;
                    case ContextRequirements.CanPasteLODBlendshape:
                        {
                            if (Selection.gameObjects.Length > 1) return false;
                            var renderer = (Selection.objects[0] as GameObject).GetComponent<Renderer>();
                            if (!renderer || !SkinnEx.HasSharedMesh(renderer)) return false;
                            var copyRefMesh = CopyRef.SharedMesh();
                            if (!copyRefMesh || renderer.GetSharedMesh().subMeshCount != copyRefMesh.subMeshCount) return false;
                            if (copyRefMesh.blendShapeCount < 1) return false;
                        }
                        break;
                    case ContextRequirements.HasBlendshapes:
                        {
                            if (Selection.gameObjects.Length > 1) return false;
                            var renderer = (Selection.objects[0] as GameObject).GetComponent<Renderer>();
                            if (!renderer || !SkinnEx.HasSharedMesh(renderer)) return false;
                            if (renderer.GetSharedMesh().blendShapeCount < 1) return false;
                        }
                        break;
                    case ContextRequirements.None:
                    default: break;
                }
                return true;
            }
        }
    }
}
